﻿using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Windows.Media;

namespace Sine
{
    //much of this code borrowed from Charles Petzold
    //http://charlespetzold.com/blog/2009/07/Simple-Electronic-Music-Sequencer-for-Silverlight.html
    public abstract class BaseMediaStreamSource : MediaStreamSource
    {
        public const int samples = 441;
        int BitsPerSample = 16;
        int SampleRate = 22050;
        protected int channelCount;
        protected MediaStreamDescription mediaStreamDescription;
        protected int byteRate;
        short blockAlign;
        protected Stream memoryStream;

        protected Dictionary<MediaSampleAttributeKeys, string> emptySampleDict = 
            new Dictionary<MediaSampleAttributeKeys, string>();



        public int Position
        {
            get
            {
                return (int) memoryStream.Position;
            }
        }

        public BaseMediaStreamSource(int channelCount, int bps, int blockalign, int samplespersec)
        {
            this.channelCount = channelCount;
            BitsPerSample = bps;
            byteRate = channelCount *
                BitsPerSample / 8 * samplespersec;
            
            blockAlign = (short)(blockalign);
            SampleRate = samplespersec;
            memoryStream = new FixedMemoryStream(byteRate);
        }

        public int ByteRate
        {
            get { return byteRate; }
        }

        protected override void OpenMediaAsync()
        {
            Dictionary<MediaStreamAttributeKeys, string> streamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();
            Dictionary<MediaSourceAttributesKeys, string> sourceAttributes = new Dictionary<MediaSourceAttributesKeys, string>();
            List<MediaStreamDescription> availableStreams = new List<MediaStreamDescription>();
            
            string format = "";
            format += ToLittleEndianString(string.Format("{0:X4}", 1));  //PCM
            format += ToLittleEndianString(string.Format("{0:X4}", channelCount));
            format += ToLittleEndianString(string.Format("{0:X8}", SampleRate));
            format += ToLittleEndianString(string.Format("{0:X8}", byteRate));
            format += ToLittleEndianString(string.Format("{0:X4}", blockAlign));
            format += ToLittleEndianString(string.Format("{0:X4}", BitsPerSample));
            format += ToLittleEndianString(string.Format("{0:X4}", 0));

            streamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = format;
            mediaStreamDescription = new MediaStreamDescription(MediaStreamType.Audio, streamAttributes);
            availableStreams.Add(mediaStreamDescription);
            sourceAttributes[MediaSourceAttributesKeys.Duration] = "0";
            sourceAttributes[MediaSourceAttributesKeys.CanSeek] = "false";
            ReportOpenMediaCompleted(sourceAttributes, availableStreams);
        }

        protected override void GetSampleAsync(MediaStreamType mediaStreamType)
        {


            
        }


        protected override void SeekAsync(long seekToTime)
        {
            this.ReportSeekCompleted(seekToTime);
        }

        protected override void CloseMedia()
        {

        }

        protected override void GetDiagnosticAsync(MediaStreamSourceDiagnosticKind diagnosticKind)
        {
            throw new NotImplementedException();
        }

        protected override void SwitchMediaStreamAsync(MediaStreamDescription mediaStreamDescription)
        {
            throw new NotImplementedException();
        }

        string ToLittleEndianString(string bigEndianString)
        {
            StringBuilder builder = new StringBuilder();

            for (int i = 0; i < bigEndianString.Length; i += 2)
                builder.Insert(0, bigEndianString.Substring(i, 2));

            return builder.ToString();
        }



    }
}
